package serviceModel;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ConcurrentLinkedQueue;
import clientRequest.ClientRequest;



/**
 * This class is responsible to pass requests from the client to the sever
 */
public class ClientRequestSender implements Runnable
{

	private static ClientRequestSender socketClientSingleton = new ClientRequestSender();//an instance of this class
	private boolean stopped; //flag- if the thread was stopped
	private Socket socket; //a socket from the client to the server
	private ObjectOutputStream out;
	private BufferedReader in;
	private String host = "localhost"; // or IP address
	
	//a queue of requests to pass to the sever
	private ConcurrentLinkedQueue<ClientRequest> requestQueue = new ConcurrentLinkedQueue<ClientRequest>();
	
	//private ctor
	private ClientRequestSender() {}
	
	/**
	 * 
	 * @return an instance of this class
	 */
	public static ClientRequestSender getInstance()
	{
		return socketClientSingleton;	
	}
	
	/**
	 * 
	 * @param request a new request from the client to the sever
	 * This method adds the input request to the requests queue
	 */
	public void AddRequestToQueue(ClientRequest request)
	 {
	  requestQueue.add(request);
	  
	  synchronized (this) {
	   notifyAll();
	  } //end synchronized
	  
	 }

	/**
	 * This method responsible to creates a connection from the client to the server (socket)
	 * in order to pass a requests 
	 */
	@Override
	public void run()  
	{
		//loop until the service has stopped and there are no more messages to pass
		while ((!stopped)||(!(requestQueue.isEmpty())))
		{
					
			//if the queue is empty - wait
			synchronized (this) {
				if (requestQueue.isEmpty())
				{
					try {
						wait();
					} catch (InterruptedException e1) {}
				}
			} //end synchronized
		
			try {
				Thread.sleep(300);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			try {
			    System.out.println("client socket to server");
			    
			    //creates a new socket
			    socket = new Socket(host,4444);
			    System.out.println("a");
			
			    out = new ObjectOutputStream(socket.getOutputStream());
			    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			    
			    System.out.println("b");
		
			    //do all the requests it should do
			    ClientRequest request=requestQueue.poll();
			    
			    System.out.println("c");
			    
			    //loop until there are no more requests
			    while (request!=null)
			    {
				     System.out.println("d");
				     //send the request to the server
				     out.writeObject(request);
				     System.out.println("e");
			
				     //get another request from the client
				     request=requestQueue.poll();
			    }
			    
			    System.out.println("f");
			    
			    //tell the server we finished for now
			    out.writeObject(new ClientRequest(null, "bye"));
			    System.out.println("g");
			   }
			   
			   catch (UnknownHostException e)
			   {
			    System.err.println("Dont know host: "+host);
			   }
			   catch (IOException e)
			   {
			    System.err.println("Cannot get IO for connection to "+host);
			   }
			   finally
			   {
			    try {
			     // close connection (Order important)
			     if (out != null)
			      out.close();
			    
			     if (in != null)
			      in.close();
			     
			     if (socket!= null)
			      socket.close();
			     
			    }catch (IOException e) {
			    	
			    }
			   }
			   
		 //end while
			
		}
		System.out.println("stop running");
	
	}

	/**
	 * This method finishes the passing of messages to the server 
	 */
	 public void stopRun() {
		    stopped = true;
		    synchronized(this) {
		       this.notify();
		    }
		 }
		 
}

